﻿using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Data.SqlClient;
using System.Text;
using System.Configuration;

public partial class _Default : System.Web.UI.Page
{
    int _prevHits = 0;
    int _wordCount = 0;

    protected void Page_Load(object sender, EventArgs e)
    {
        string reqWord = Page.Request["word"];

        Dictionary<string, int> words = new Dictionary<string, int>();

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["WHTCDb"].ConnectionString))
        {
            string q;

            if (string.IsNullOrEmpty(reqWord))
                q = "select top 140 * from words where exclude=0 and datediff(hour, datetimeupdated, getdate())<6 order by hits desc";
            else
                q = "select distinct top 140 w.* from words w, titles t where t.word=w.word and t.title like '%" + reqWord + "%' and datediff(day, datetimeupdated, getdate())<7 order by hits desc";

            conn.Open();
            SqlCommand cmdWords = new SqlCommand(q, conn);
            SqlDataReader rdrWords = cmdWords.ExecuteReader();

            while (rdrWords.Read())
            {
                words.Add(rdrWords.GetString(0), rdrWords.GetInt32(1));
            }

            if (words.Count == 0) return;

            rdrWords.Close();
            SqlCommand cmdTitles = new SqlCommand("select top 10 * from Titles where word=@word and link is not null order by datetimecreated desc", conn);
            cmdTitles.Parameters.Add("@word", System.Data.SqlDbType.NVarChar);

            foreach (string word in words.Keys)
            {
                AddWord(word, words[word]);
            }
            if (!string.IsNullOrEmpty(reqWord))
            {
                HyperLink titleLink = new HyperLink();
                titleLink.Text = " | " + reqWord.ToUpper();
                titleLink.NavigateUrl = "Default.aspx?word=" + reqWord;
                pathPanel.Controls.Add(titleLink);

                Dictionary<string, string> titles = new Dictionary<string, string>();
                cmdTitles.Parameters["@word"].Value = reqWord;
                SqlDataReader rdrTitles = cmdTitles.ExecuteReader();
                while (rdrTitles.Read())
                {
                    titles.Add(rdrTitles.GetString(1), (rdrTitles[2] == DBNull.Value ? "" : rdrTitles.GetString(2)));
                }
                rdrTitles.Close();

                string titlesString = "";
                foreach (string t in titles.Keys)
                {
                    string link = titles[t];
                    if (string.IsNullOrEmpty(link))
                        titlesString += string.Format(" | {0}", t);
                    else
                        titlesString += string.Format(
                            " | <a href='{0}' target='_blank'>{1}</a>", titles[t],
                            ReplaceString(t, reqWord, "<b>" + reqWord.ToUpper() + "</b>", StringComparison.OrdinalIgnoreCase));
                }

                titlesString = titlesString.TrimStart(' ', '|');

                titlesPanel.InnerHtml = titlesString;
            }
        }
    }

    private void AddWord(string word, int hits)
    {
        _wordCount++;
        int hitDelta = _prevHits - hits;
        int fontSizeDelta = (hitDelta < 2 ? 2 : hitDelta) * _wordCount;

        int fontSize = System.Convert.ToInt32(60 - fontSizeDelta);

        Random r = new Random(DateTime.Now.Millisecond * fontSize * DateTime.Now.DayOfYear);

        Label l = new Label();
        l.Text = word;
        l.Font.Name = "Arial";
        l.ForeColor = Color.FromArgb(r.Next(0, 200), r.Next(0, 200), r.Next(0, 200));

        l.Font.Size = new FontUnit((fontSize > 8 ? fontSize : 8));

        Box d = GetLabelBox(l, r);

        l.Style.Add(HtmlTextWriterStyle.Position, "absolute");
        l.Style.Add(HtmlTextWriterStyle.ZIndex, _wordCount.ToString());
        l.Style.Add(HtmlTextWriterStyle.Left, d.Left.ToString() + "px");
        l.Style.Add(HtmlTextWriterStyle.Top, d.Top.ToString() + "px");
        l.Style.Add(HtmlTextWriterStyle.Cursor, "pointer");
        l.Attributes.Add("onclick", string.Format("javascript:window.location.href='Default.aspx?word={0}'", word));

        cloudPanel.Controls.Add(l);

        _prevHits = hits;
    }

    static public string ReplaceString(string str, string oldValue, string newValue, StringComparison comparison)
    {
        StringBuilder sb = new StringBuilder();

        int previousIndex = 0;
        int index = str.IndexOf(oldValue, comparison);
        while (index != -1)
        {
            sb.Append(str.Substring(previousIndex, index - previousIndex));
            sb.Append(newValue);
            index += oldValue.Length;

            previousIndex = index;
            index = str.IndexOf(oldValue, index, comparison);
        }
        sb.Append(str.Substring(previousIndex));

        return sb.ToString();
    }

    private class Box
    {
        public Box(int h, int w) { Height = h; Width = w; }
        public int Height { get; set; }
        public int Width { get; set; }
        public int Top { get; set; }
        public int Left { get; set; }
        public int Right {
            get { return Left + Width; }
        }
        public int Bottom
        {
            get { return Top + Height; }
        }
        public int HorMiddle
        {
            get { return Left + Width / 2; }
        }
        public int VerMiddle
        {
            get { return Top + Height / 2; }
        }
    }

    List<Box> _boxes = new List<Box>();

    private Box GetLabelBox(Label label, Random r)
    {
        Font objFont = new Font(label.Font.Name, System.Convert.ToInt32(label.Font.Size.Unit.Value));
        Bitmap objBitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(objBitmap);
        SizeF textSize = g.MeasureString(label.Text, objFont);
        g.Dispose();

        Box b = new Box((int)textSize.Height, (int)textSize.Width);

        GetTopLeft(r, b, 0);

        _boxes.Add(b);

        return b;
    }

    private void GetTopLeft(Random r, Box b, int attempts)
    {
        b.Left = r.Next(0, System.Convert.ToInt32(cloudPanel.Width.Value - (b.Width)));
        b.Top = r.Next(0, System.Convert.ToInt32(cloudPanel.Height.Value - (b.Height)));

        foreach (Box thisBox in _boxes)
        {
            if (++attempts < 10000 && b.HorMiddle > thisBox.Left && b.HorMiddle < thisBox.Right && b.VerMiddle > thisBox.Top && b.VerMiddle < thisBox.Bottom)
            {
                GetTopLeft(r, b, ++attempts);
                break;
            }
        }
    }
}
